package top.xbaoziplus.company.common;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import top.xbaoziplus.company.empty.UserInfo;
import top.xbaoziplus.company.service.UserInfoService;

import java.util.ArrayList;
import java.util.List;

/**
 * @author xBaozi
 * @version 1.0
 * @classname DataListener
 * @description 自定义读Excel监听器
 * @date 2022/5/3 17:04
 */
@Slf4j
@Setter
@EqualsAndHashCode(callSuper = true)
public class DataListener extends AnalysisEventListener<UserInfo> {
    /** 每隔100条存储数据库，然后清理list ，方便内存回收*/
    private static final int BATCH_COUNT = 100;

    /** 记录失败的数据条数 */
    @Getter
    private Integer failNums = 0;

    @Getter
    private Integer successNums = 0;

    private UserInfoService userInfoService;

    public DataListener(UserInfoService userInfoService){
        this.userInfoService = userInfoService;
    }

    /** 缓存的数据 */
    List<UserInfo> list = new ArrayList<UserInfo>();

    /**
     * @description 读取数据所执行的逻辑
     * @author xBaozi
     * @date 17:14 2022/5/3
     **/
    @Override
    public void invoke(UserInfo instance, AnalysisContext analysisContext) {
        log.info("读取到了数据{}", instance);
        list.add(instance);
        // 达到BATCH_COUNT存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (list.size() >= BATCH_COUNT){
            this.saveData();
            list.clear();
        }
    }

    /**
     * @description 所有数据读取完毕之后将数据存放到数据库中
     * @author xBaozi
     * @date 17:15 2022/5/3
     **/
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 确保最后遗留的数据也存储到数据库
        this.saveData();
        log.info("所有数据导入成功");
    }

    /**
     * @description 将数据存放到数据库中
     * @author xBaozi
     * @date 17:09 2022/5/3
     **/
    private void saveData() {
        for (UserInfo data : list) {
            log.info("{}开始存放数据库……", data);
            try {
                this.userInfoService.save(data);
                this.successNums++;
            } catch (NullPointerException e) {
                log.info(e.toString());
                this.failNums++;
            }
        }
    }
}
